package com.gcb.service.impl;

import cn.hutool.core.util.StrUtil;
import com.gcb.common.constant.CacheConstants;
import com.gcb.common.core.domain.entity.GcbUser;
import com.gcb.common.core.redis.RedisCache;
import com.gcb.common.enums.LoginType;
import com.gcb.common.exception.ServiceException;
import com.gcb.common.exception.user.UserNotExistsException;
import com.gcb.common.utils.PasswordUtils;
import com.gcb.common.utils.StringUtils;
import com.gcb.common.utils.TokenUtil;
import com.gcb.service.IGcbUserService;
import com.gcb.service.ILoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.regex.Pattern;

@Service
public class LoginService implements ILoginService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private IGcbUserService gcbUserService;

    @Autowired
    private TokenUtil tokenUtil;

    @Override
    public String login(String phone, String password, String code, String loginType) {
        // 登录前置校验
        boolean isPassword = loginPreCheck(phone, password, code, loginType);
        // 查询用户
        GcbUser gcbUser = gcbUserService.getByMobile(phone);
        if (Objects.isNull(gcbUser)) {
            throw new ServiceException("手机号未注册");
        }
        // 校验密码
        if (isPassword) {
            String passwordFromDb = gcbUser.getPassword();
            if (!PasswordUtils.matchesPassword(password, passwordFromDb)) {
                throw new ServiceException("密码错误");
            }
        }
        // 生成token
        return tokenUtil.getToken(gcbUser.getId());
    }


    /**
     * 登录前置校验
     *
     * @param phone    手机号
     * @param password 用户密码
     */
    private boolean loginPreCheck(String phone, String password, String code, String loginType) {
        boolean isPassword = false;
        if (StrUtil.isEmpty(phone)) {
            // TODO
            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new RuntimeException("手机号不能为空");
        }
        if (LoginType.SMS.getCode().equals(loginType) && StrUtil.isEmpty(code)) {
            // TODO
            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new RuntimeException("验证码不能为空");
        }
        if (LoginType.ACCOUNT.getCode().equals(loginType) && StrUtil.isEmpty(password)) {
            // TODO
            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new RuntimeException("密码不能为空");
        }
        // IP黑名单校验
//        String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
//        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
//            // TODO
//            // AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
//            throw new BlackListException();
//        }
        // 在判断是密码还是验证码登录 默认账号密码登录
        if (StringUtils.isBlank(loginType) || LoginType.ACCOUNT.getCode().equals(loginType)) {
            if (StringUtils.isBlank(password)) {
                throw new ServiceException("用户密码不能为空");
            }
            isPassword = true;
        } else if (LoginType.SMS.getCode().equals(loginType)) {
            // 短信验证码校验
            validateVerifyCode(phone, code);
            // 验证码校验后 删除验证码
            String verifyKey = CacheConstants.APP_VERIFY_CODE_KEY + StringUtils.nvl(phone, "");
            redisCache.deleteObject(verifyKey);
        } else {
            throw new ServiceException("请选择正确的登录方式");
        }
        return isPassword;
    }

    /**
     * app端验证码登录-校验验证码
     *
     * @param phone 电话
     * @param code  验证码
     * @return 结果
     */
    private void validateVerifyCode(String phone, String code) {
        if (!Pattern.compile("^[1][1,2,3,4,5,6,7,8,9][0-9]{9}$").matcher(phone).matches()) {
            throw new ServiceException("手机号格式错误");
        }

        String verifyKey = CacheConstants.APP_VERIFY_CODE_KEY + StringUtils.nvl(phone, "");
        Long expireTime = redisCache.getExpire(verifyKey);
        if (expireTime != null && expireTime.longValue() > 0) {
            String verifyCodeCache = redisCache.getCacheObject(verifyKey);
            if (StringUtils.isBlank(verifyCodeCache)) {
                throw new ServiceException("系统错误，请重新发送验证码");
            }
            if (!code.equals(verifyCodeCache)) {
                // TODO
                // AsyncManager.me().execute(AsyncFactory.recordLogininfor(phone, Constants.LOGIN_FAIL, MessageUtils.message("user.smscode.error")));
                throw new ServiceException("验证码错误");
            }
        } else {
            // 缓存过期
            throw new ServiceException("此验证码已过期，请重新发送验证码");
        }
    }


}
